<?php

class AggregateModel extends EntityModel
{

  protected $associations = array();

  /**
   *
   * @return Entity
   */
  public function factory($model = null, $data = null)
  {
    $class = $this->getClass();

    if ($class) {
      $obj = new $class($data);
    }
    else {
      $obj = new CustomAggregate($model, $data);
    }

    return $obj;
  }

  /**
   *
   * @return void
   */
  public function associationExists($name)
  {
    if (! isset($this->model['associations'][$name])) {
      throw new AssociationNotFoundException("Association <b>$name</b> not found");
    }
  }

  /**
   *
   * @return array
   */
  public function getAssociations()
  {
    return $this->model['associations'];
  }

  /**
   *
   * @return AssociationModel
   */
  public function getAssociation($name)
  {
    $this->associationExists($name);

    return $this->model['associations'][$name];
  }

  public function factoryAssociation(Aggregate $source, $name)
  {
    $id = spl_object_hash($source);

    if (! isset($this->associations[$id][$name])) {
      $model = $this->getAssociation($name);

      if (isset($model['target'])) {
        $target = $model['target'];
      }
      elseif (isset($model[0])) {
        $target = $model[0];
      }
      else {
        throw new DomainDefinitionException('Could not determine association target');
      }

      if (isset($model['type'])) {
        $type = $model['type'];
      }
      elseif (isset($model[1])) {
        $type = $model[1];
      }
      else {
        throw new DomainDefinitionException('Could not determine association type');
      }

      $type = (strtolower($type) == 'habtm') ? 'HasAndBelongsToMany' : Inflector::camelize($type);

      $class = $type . 'Association';

      $this->associations[$id][$name] = new $class($source, $name, $target);
    }

    return $this->associations[$id][$name];
  }

}
